﻿/***************************
 * Author:蓝海洋
 * Copyright:Ehai工作室
 * CreateDate:2009-7-12
 **************************/

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.SessionState;

using System.IO;
using System.IO.Compression;
using System.Xml;
using System.Web.UI;
using System.Text.RegularExpressions;

namespace Ehai.Web.Framework
{
    #region 配置处理

    //II6: 在Web.config文件<configuration><system.web></system.web></configuration>中添加以下节

    /*
        <httpHandlers>
          <!--   <add path="Reserved.ReportViewerWebControl.axd" verb="*" type="Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
        validate="false" /> -->
          <!--<add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="false" />-->
          <add path="*.aspx" verb="*" type="Ehai.Web.Framework.WebHttpHandle" validate="false" />
        </httpHandlers>
        <httpModules>
          <add name="HandlePoint" type="Ehai.Web.Framework.HandlePoint"/>
        </httpModules>
    */
    //II7: 
    /*
        IIS 7 has introduces two major changes from earlier version of IIS that affect SlickUpload. First, IIS 7 Integrated Mode uses the <system.webServer> tag to configure HttpModules and HttpHandlers. Second, IIS 7 adds a request filtering module that controls request size. To configure your application to support SlickUpload under IIS 7, make the following changes to your web.config:
        Move the httpModule and httpHandler sections – Move configuration from the <system.web> web.config section to the <system.webServer> section. 
        Remove the existing SlickUpload references from the <system.web> httpModule and httpHandler sections 
        Add the following section to your web.config: 
        <system.webServer> 
            <handlers> 
                <add name="SlickUploadHandler" path="SlickUpload.axd" verb="GET,POST" type="Krystalware.SlickUpload.SlickUploadHandler, Krystalware.SlickUpload" /> 
            </handlers> 
            <modules> 
                <add name="SlickUploadModule" type="Krystalware.SlickUpload.HttpUploadModule, Krystalware.SlickUpload" preCondition="managedHandler" /> 
            </modules> 
        </system.webServer>
        Add a configuration section to increase the request filtering allowed size
        Add the following section inside your <system.webServer> configuration section: 
        <security> 
            <requestFiltering> 
                <requestLimits maxAllowedContentLength="2072576000"/> 
            </requestFiltering> 
        </security>
        If you get an error such as "The requested page cannot be accessed because the related configuration data for the page is invalid" when you add the requestFiltering section to your web.config, you'll have to modify the IIS 7 applicationHost.config file to enable you to configure request filtering at the application level instead of the machine level. To do this, open the %windir%\System32\inetsrv\config\applicationHost.config file in a text editor and change the following line:

        <section name="requestFiltering" overrideModeDefault="Deny" />
        to read:

        <section name="requestFiltering" overrideModeDefault="Allow" />
        If you are in a hosted environment such that you can't manually change the applicationHost.config, request that your hosting provider makes the above change.
     */

    #endregion

    /// <summary>
    ///	<httpModules>
    /// 	<add name="EntryPoint" type="Ehai.WebFramework.EntryPoint"/>
    /// </httpModules>
    /// </summary>
    sealed class HandlePoint : System.Web.IHttpModule, System.Web.SessionState.IRequiresSessionState
    {
        #region IHttpModule 成员

        void IHttpModule.Dispose()
        {
        }

        /// <summary>
        /// HttpModule初始化
        /// </summary>
        /// <param name="context"></param>
        void IHttpModule.Init(HttpApplication context)
        {
            //设置BeginRequest事件，区分文件上传和系统入口
            context.BeginRequest += new EventHandler(context_BeginRequest);

            //系统入口
            context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
        }

        #endregion

        #region 系统入口前预处理：HttpApplication的BeginRequest事件处理

        /// <summary>
        /// 该事件在所有事件前触发
        /// 在此位置为1、是否文件上传 2、进入系统入口 进行设置
        /// 注意此时Session还不存在 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void context_BeginRequest(object sender, EventArgs e)
        {

            //分析进入请求
            //加入认证判断，在认证模式下
            //如果认证没有通过，直接在这里返回
            //在认证模式下可以通过命令激活请求关闭码，通过关闭码可以关闭"所有请求响应"
            //当然也可以通过激活码开启"所有请求响应"

            ContextInfo wev = ContextInfo.Instance();

            wev.Response.Cache.SetNoStore();
            //基本信息认定是否合理请求,否则返回为空
            if (wev.Request.UrlReferrer != null && wev.Request.Url.Authority != wev.Request.UrlReferrer.Authority)
            {
                wev.Response.Write("非法访问资源，请先登陆再重新登陆。");
                wev.End();
                return;
            }
            //设置压缩传输
            CompressHttp.Entry(wev);

        }
       
        #endregion

        #region 系统入口处理：HttpApplication的PreRequestHandlerExecute事件处理
        /// <summary>
        /// 此时Session已存在
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void context_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            ContextInfo wev = ContextInfo.Instance();
            //wev.Response.Write(FileHandle.SanitizeFileName("www.baidi.com/fss.ss/aa.html"));
            //wev.Response.Write(FileHandle.SanitizeFileName("c:/file/dfj./bbb.jpg"));
            //wev.Response.Write(FileHandle.SanitizeFileName("file/imag/ccc.gif"));

            //本框架处理
            bool bNoPage = false;
            try
            {
                //if (EntryTreator.Entry(wev))
                string pFileName = wev.Request.AppRelativeCurrentExecutionFilePath;

#if DEBUG
                if (
                    pFileName.ToLower().EndsWith(".html") || pFileName.ToLower().EndsWith(".htm") ||
                    pFileName.ToLower().EndsWith(".js") || pFileName.ToLower().EndsWith(".jpg") ||
                    pFileName.ToLower().EndsWith(".jpeg") || pFileName.ToLower().EndsWith(".png") ||
                    pFileName.ToLower().EndsWith(".css") || pFileName.ToLower().EndsWith(".bmp") ||
                    pFileName.ToLower().EndsWith(".gif") || pFileName.ToLower().EndsWith(".xml") ||
                    pFileName.ToLower().EndsWith(".swf"))
                    return;

                #region 获得帮助信息

#if DEBUG

                if (wev.Parameters("msghelp") != null)
                {
                    
                    switch (wev.Parameters("msghelp").ToString().ToLower())
                    {
                        case "all":
                            wev.Response.Write(Rules.HelpInfo.GetAllMsgInfo());
                            break;
                        case "detail":
                            if (wev.Parameters("msgname") != null)
                            {
                                wev.Response.Write(Rules.HelpInfo.GetHelpDetail(wev.Parameters("msgname").ToString().ToLower()));
                            }
                            break;
                        case "param":
                            if (wev.Parameters("msgname") != null)
                            {
                                wev.Response.Write(Rules.HelpInfo.GetParametersInfo(wev.Parameters("msgname").ToString().ToLower()));
                            }
                            break;
                    }

                    wev.End();
                    return;
                }

#endif

                #endregion

#endif
                #region 系统处理消息

                MessageHandle mh = new MessageHandle();
                int sysStatus = mh.HandleEntry(wev);
                if (sysStatus == 0)
                {
                    if (mh.ResponseHtmlString.Length > 0)
                        wev.Response.Write(mh.ResponseHtmlString);
                }

                #endregion

                #region 自定义处理请求

#if CUSTOMER

                //注意：自定义处理程序的请求中不能够出现msg变量
                int cumStatus = -1;
                if (sysStatus == -1)
                {
                    if (wev.RuleHandleType.ContainsKey(pFileName))
                    {
                        Rules.IRuleHandle rh = Rules.RuleFactory.GetRuleHandle(wev.RuleHandleType[pFileName]);

                        if (rh != null)
                        {
                            cumStatus = rh.WebMain(wev);
                            if (cumStatus == 0)
                            {
                                if (rh.ResponseHtmlString.Length > 0)
                                    wev.Response.Write(rh.ResponseHtmlString);
                            }
                        }
                    }
                }

#endif
                #endregion

#if CUSTOMER
                if (sysStatus != 0 && cumStatus != 0)
                {
                    bNoPage = true;
                }
#else
                if (sysStatus != 0)
                {
                    bNoPage = true;
                }
#endif


            }
            catch (WebException wex)
            {
                wev.Response.Write(wex.GetResponseInfo());
            }
            catch (Exception ex)
            {
                wev.Response.Write(ex.Message);
            }

            if (!bNoPage)
            {
                wev.End();
                return;
            }

            //本框架处理完毕

            Dictionary<string, string> dict = wev.GetConfigNodeDict("/Root/Options/Option[@name='IsEffectWebServerHandle']");

            string opIsEffect = dict == null ? "false" : dict["value"].ToLower();
            try
            {
                if (opIsEffect == "true")
                {
                    noPageToWhere(wev);
                }
                else
                {
                    try
                    {
                        IHttpHandler ihh = (new WebHttpHandleFactory()).GetHandler(wev.Current, wev.Request.RequestType,
                            wev.Request.Path, wev.Request.PhysicalApplicationPath);
                        ihh.ProcessRequest(wev.Current);
                    }
                    catch (Exception ex)
                    {
                        noPageToWhere(wev, ex);
                    }
                }
                wev.End();
                return;
            }
            catch (Exception ex)
            {
                wev.Response.Write(ex.Message);
                wev.End();
                return;
            }
        }

        #endregion

        #region 错误处理

        private void noPageToWhere(ContextInfo wev)
        {
            //wev.Response.Write(WebCache.GetFileContent(wev,"nopageerror.htm",null,null));
            noPageToWhere(wev, null);
        }

        private void noPageToWhere(ContextInfo wev, Exception ex)
        {
            Dictionary<string, string> errDict = wev.GetApplicationDictFromConfigAttribute("NopageError", "/Root/Options/NoPage");
            if (errDict == null || errDict["from"] == null) return;

            Regex reg = new Regex(@"\{([_a-zA-Z]+[_a-zA-Z0-9]*)\}", RegexOptions.None);
            bool bCacheChanged;
            if (ex != null)
            {
                if (errDict.ContainsKey("reason") && errDict["reason"] == ex.Message)
                    bCacheChanged = false;
                else
                {
                    bCacheChanged = true;
                    errDict["reason"] = ex.Message;
                }
            }
            else
            {
                bCacheChanged = true;
                errDict["reason"] = String.Empty;
            }

            if (!errDict["to"].StartsWith(HttpRuntime.AppDomainAppVirtualPath))
            {
                errDict["to"] = HttpRuntime.AppDomainAppVirtualPath +
                    (errDict["to"].StartsWith("/") ? errDict["to"] : "/" + errDict["to"]);
            }
            errDict["toFile"] = Path.Combine(HttpRuntime.AppDomainAppPath,
                errDict["to"].TrimStart(HttpRuntime.AppDomainAppVirtualPath.ToCharArray())
                .Replace('/', Path.DirectorySeparatorChar).TrimStart(Path.DirectorySeparatorChar));
            if (File.Exists(errDict["toFile"]))
            {
                wev.Response.Write(WebCache.GetFileContent(wev, errDict["from"], reg, new MatchEvaluator(replaceByConfigAttribute), bCacheChanged, false));
            }
            else
            {
                wev.Response.Write(getErrorNopageInfoFromConfigFile(wev));
            }
        }

        private string replaceByConfigAttribute(Match m)
        {
            try
            {
                Dictionary<string, string> errDict = ContextInfo.Instance().GetApplicationDictFromConfigAttribute("NopageError", "/Root/Options/NoPage");
                return ((errDict == null) ? String.Empty : errDict[m.Groups[1].Value]);
            }
            catch
            {
                return String.Empty;
            }
        }

        private string getErrorNopageInfoFromConfigFile(ContextInfo wev)
        {
            Dictionary<string, string> errDict = wev.GetApplicationDictFromConfigAttribute("NopageError", "/Root/Options/NoPage");
            return ((errDict == null) ? String.Empty : errDict["info"]);
        }

        #endregion

    }
}
